"""
统一服务层 - 整合天气、导航、AI文本、TTS、音乐生成功能
提供降级处理，确保服务可用性
"""
import os
import logging
from typing import Dict, Optional, Tuple, List
from datetime import datetime
from flask import current_app

from app.models.location import Location
from app.models.poi import POI
from app.models.weather_data import WeatherData

logger = logging.getLogger(__name__)


class UnifiedService:
    """统一服务层，整合所有外部API并提供降级处理"""
    
    def __init__(self):
        """初始化统一服务"""
        self._weather_service = None
        self._route_planner = None
        self._ai_service = None
    
    @property
    def weather_service(self):
        """懒加载天气服务"""
        if self._weather_service is None:
            from app.services.weather_service import WeatherService
            qweather_key = current_app.config.get('QWEATHER_KEY', '')
            redis_url = current_app.config.get('REDIS_URL', 'redis://localhost:6379/0')
            cache_duration = current_app.config.get('WEATHER_CACHE_DURATION_SECONDS', 1800)
            self._weather_service = WeatherService(qweather_key, redis_url, cache_duration)
        return self._weather_service
    
    @property
    def route_planner(self):
        """懒加载路线规划服务"""
        if self._route_planner is None:
            from app.services.route_planner_service import RoutePlannerService
            tencent_map_key = current_app.config.get('TENCENT_MAP_KEY', '')
            self._route_planner = RoutePlannerService(tencent_map_key)
        return self._route_planner
    
    @property
    def ai_service(self):
        """懒加载AI服务"""
        if self._ai_service is None:
            from app.services.ai_generation_service import AIGenerationService
            api_key = current_app.config.get('OPENAI_API_KEY', '')
            api_base = current_app.config.get('OPENAI_API_BASE', 'https://api.openai.com/v1')
            self._ai_service = AIGenerationService(api_key, api_base)
        return self._ai_service

    # ==================== 天气服务 ====================
    
    def get_weather(self, latitude: float, longitude: float) -> Dict:
        """
        获取天气信息（带降级处理）
        
        Args:
            latitude: 纬度
            longitude: 经度
            
        Returns:
            天气数据字典
        """
        try:
            location = Location(latitude=latitude, longitude=longitude, accuracy=10.0)
            weather = self.weather_service.get_current_weather(location)
            is_suitable, warning = self.weather_service.is_weather_suitable(weather)
            
            return {
                'success': True,
                'data': {
                    'temperature': weather.temperature,
                    'condition': weather.condition,
                    'humidity': weather.humidity,
                    'wind_speed': weather.wind_speed,
                    'aqi': weather.aqi,
                    'timestamp': weather.timestamp.isoformat() if weather.timestamp else datetime.utcnow().isoformat()
                },
                'is_suitable': is_suitable,
                'warning': warning,
                'is_mock': False
            }
        except Exception as e:
            logger.warning(f"Weather service failed, using mock data: {e}")
            return self._get_mock_weather()
    
    def _get_mock_weather(self) -> Dict:
        """返回模拟天气数据"""
        return {
            'success': True,
            'data': {
                'temperature': 22.0,
                'condition': '晴',
                'humidity': 60,
                'wind_speed': 10.0,
                'aqi': 50,
                'timestamp': datetime.utcnow().isoformat()
            },
            'is_suitable': True,
            'warning': None,
            'is_mock': True
        }
    
    # ==================== 导航服务 ====================
    
    def search_pois(self, latitude: float, longitude: float, radius: int = 3000) -> Dict:
        """
        搜索附近POI（带降级处理）
        
        Args:
            latitude: 纬度
            longitude: 经度
            radius: 搜索半径（米）
            
        Returns:
            POI列表
        """
        try:
            location = Location(latitude=latitude, longitude=longitude, accuracy=10.0)
            pois = self.route_planner.search_nearby_pois(location, radius)
            
            return {
                'success': True,
                'data': [poi.to_dict() for poi in pois],
                'count': len(pois),
                'is_mock': False
            }
        except Exception as e:
            logger.warning(f"POI search failed, using mock data: {e}")
            return self._get_mock_pois(latitude, longitude)
    
    def _get_mock_pois(self, latitude: float, longitude: float) -> Dict:
        """返回模拟POI数据"""
        mock_pois = [
            {
                'id': 'mock_poi_1',
                'name': '中心公园',
                'latitude': latitude + 0.005,
                'longitude': longitude + 0.003,
                'category': '公园广场',
                'description': '城市中心的休闲公园',
                'distance': 500
            },
            {
                'id': 'mock_poi_2',
                'name': '历史博物馆',
                'latitude': latitude + 0.008,
                'longitude': longitude - 0.002,
                'category': '文化场馆',
                'description': '展示本地历史文化的博物馆',
                'distance': 800
            },
            {
                'id': 'mock_poi_3',
                'name': '滨河步道',
                'latitude': latitude - 0.003,
                'longitude': longitude + 0.006,
                'category': '风景名胜',
                'description': '沿河而建的景观步道',
                'distance': 600
            }
        ]
        return {
            'success': True,
            'data': mock_pois,
            'count': len(mock_pois),
            'is_mock': True
        }
    
    def get_walking_route(self, start_lat: float, start_lng: float, 
                          end_lat: float, end_lng: float) -> Dict:
        """
        获取步行路线（带降级处理）
        
        Args:
            start_lat, start_lng: 起点坐标
            end_lat, end_lng: 终点坐标
            
        Returns:
            路线数据
        """
        try:
            import requests
            
            tencent_map_key = current_app.config.get('TENCENT_MAP_KEY', '')
            url = "https://apis.map.qq.com/ws/direction/v1/walking"
            params = {
                'key': tencent_map_key,
                'from': f"{start_lat},{start_lng}",
                'to': f"{end_lat},{end_lng}"
            }
            
            response = requests.get(url, params=params, timeout=10)
            result = response.json()
            
            if result.get('status') == 0:
                route_result = result.get('result', {})
                routes = route_result.get('routes', [])
                if routes:
                    route = routes[0]
                    return {
                        'success': True,
                        'data': {
                            'distance': route.get('distance', 0),
                            'duration': route.get('duration', 0),
                            'polyline': route.get('polyline', [])
                        },
                        'is_mock': False
                    }
            
            raise Exception(f"Route API error: {result.get('message', 'Unknown')}")
            
        except Exception as e:
            logger.warning(f"Route service failed, using mock data: {e}")
            return self._get_mock_route(start_lat, start_lng, end_lat, end_lng)
    
    def _get_mock_route(self, start_lat: float, start_lng: float,
                        end_lat: float, end_lng: float) -> Dict:
        """返回模拟路线数据"""
        # 简单计算直线距离
        import math
        R = 6371000  # 地球半径（米）
        lat1, lat2 = math.radians(start_lat), math.radians(end_lat)
        dlat = math.radians(end_lat - start_lat)
        dlng = math.radians(end_lng - start_lng)
        a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlng/2)**2
        distance = R * 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
        
        return {
            'success': True,
            'data': {
                'distance': int(distance),
                'duration': int(distance / 80 * 60),  # 假设步行速度80米/分钟
                'polyline': []  # 简化版无详细路线
            },
            'is_mock': True
        }

    # ==================== AI文本生成服务 ====================
    
    def generate_poi_introduction(self, poi_name: str, poi_category: str,
                                   poi_description: str = '', weather: Dict = None) -> Dict:
        """
        生成POI介绍文本（带降级处理）
        
        Args:
            poi_name: 景点名称
            poi_category: 景点类别
            poi_description: 景点描述
            weather: 天气信息
            
        Returns:
            生成的介绍文本
        """
        try:
            # 创建临时POI对象
            poi = POI(
                name=poi_name,
                category=poi_category,
                description=poi_description or f"{poi_name}是一个值得游览的{poi_category}",
                latitude=0, longitude=0
            )
            
            context = {'weather': weather} if weather else {}
            introduction = self.ai_service.generate_poi_introduction(poi, context)
            
            return {
                'success': True,
                'data': {
                    'text': introduction,
                    'poi_name': poi_name
                },
                'is_mock': False
            }
        except Exception as e:
            logger.warning(f"AI text generation failed, using fallback: {e}")
            return self._get_fallback_introduction(poi_name, poi_category, poi_description)
    
    def _get_fallback_introduction(self, poi_name: str, poi_category: str,
                                    poi_description: str = '') -> Dict:
        """返回降级的介绍文本"""
        templates = {
            '公园': f"欢迎来到{poi_name}！这是一处宁静优美的城市绿地，是散步休闲的好去处。漫步其中，感受大自然的气息，让身心得到放松。",
            '博物馆': f"欢迎参观{poi_name}！这里收藏着丰富的历史文化珍品，每一件展品都诉说着独特的故事。让我们一起探索历史的奥秘。",
            '风景名胜': f"欢迎来到{poi_name}！这是一处风景秀丽的名胜之地，自然风光与人文景观交相辉映。驻足欣赏，感受这份独特的美。",
            '文化场馆': f"欢迎来到{poi_name}！这里是文化艺术的殿堂，承载着深厚的文化底蕴。让我们一起感受艺术的魅力。",
        }
        
        # 匹配类别
        text = None
        for key, template in templates.items():
            if key in poi_category:
                text = template
                break
        
        if not text:
            text = f"欢迎来到{poi_name}！{poi_description or '这是一个值得探索的地方，让我们一起发现它的魅力。'}"
        
        return {
            'success': True,
            'data': {
                'text': text,
                'poi_name': poi_name
            },
            'is_mock': True
        }
    
    # ==================== TTS语音合成服务 ====================
    
    def text_to_speech(self, text: str, voice: str = 'alloy') -> Dict:
        """
        文本转语音（带降级处理）
        
        Args:
            text: 要转换的文本
            voice: 语音类型 (alloy, echo, fable, onyx, nova, shimmer)
            
        Returns:
            音频数据（base64编码）或错误信息
        """
        import base64
        
        try:
            if not text or not text.strip():
                raise ValueError("文本不能为空")
            
            audio_bytes = self.ai_service.text_to_speech(text, voice)
            
            return {
                'success': True,
                'data': {
                    'audio_base64': base64.b64encode(audio_bytes).decode('utf-8'),
                    'format': 'mp3',
                    'size': len(audio_bytes)
                },
                'is_mock': False
            }
        except Exception as e:
            logger.warning(f"TTS service failed: {e}")
            return {
                'success': False,
                'error': str(e),
                'message': 'TTS服务暂时不可用，请稍后重试',
                'is_mock': True
            }
    
    # ==================== 音乐生成服务 ====================
    
    def generate_music(self, poi_name: str, poi_category: str,
                       weather_condition: str = '晴', mood: str = 'relaxing') -> Dict:
        """
        生成背景音乐（带降级处理）
        
        Args:
            poi_name: 景点名称
            poi_category: 景点类别
            weather_condition: 天气状况
            mood: 心情/氛围
            
        Returns:
            音乐信息（URL或预设音乐）
        """
        try:
            suno_api_key = current_app.config.get('SUNO_API_KEY', '')
            
            if not suno_api_key:
                logger.info("Suno API key not configured, using preset music")
                return self._get_preset_music(poi_category, weather_condition, mood)
            
            # 创建临时对象
            poi = POI(name=poi_name, category=poi_category, description='', latitude=0, longitude=0)
            weather = WeatherData(
                temperature=22.0, condition=weather_condition,
                humidity=60, wind_speed=10.0, aqi=None, timestamp=datetime.utcnow()
            )
            
            result = self.ai_service.generate_background_music(poi, weather, mood, suno_api_key)
            
            if result.get('generated'):
                import base64
                return {
                    'success': True,
                    'data': {
                        'audio_base64': base64.b64encode(result['audio_bytes']).decode('utf-8'),
                        'duration': result.get('duration', 60),
                        'format': 'mp3'
                    },
                    'is_mock': False
                }
            else:
                return self._get_preset_music(poi_category, weather_condition, mood)
                
        except Exception as e:
            logger.warning(f"Music generation failed, using preset: {e}")
            return self._get_preset_music(poi_category, weather_condition, mood)
    
    def _get_preset_music(self, poi_category: str, weather_condition: str, mood: str) -> Dict:
        """返回预设音乐"""
        # 根据类别和天气选择预设音乐
        music_map = {
            '公园': {'name': '清晨漫步', 'style': 'light'},
            '博物馆': {'name': '古典回响', 'style': 'classical'},
            '风景名胜': {'name': '自然之声', 'style': 'nature'},
            '文化场馆': {'name': '艺术氛围', 'style': 'ambient'},
        }
        
        # 匹配类别
        music_info = {'name': '轻松时光', 'style': 'ambient'}
        for key, info in music_map.items():
            if key in poi_category:
                music_info = info
                break
        
        return {
            'success': True,
            'data': {
                'name': music_info['name'],
                'style': music_info['style'],
                'url': f"/static/music/preset/{music_info['style']}.mp3",
                'duration': 180,
                'is_preset': True
            },
            'is_mock': True,
            'message': '使用预设音乐（Suno API未配置）'
        }
